package com.lineage.server.datatables;

import com.lineage.DatabaseFactory;
import com.lineage.server.model.L1NpcTalkData;
import com.lineage.server.model.shop.L1Shop;
import com.lineage.server.templates.L1ShopItem;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ShopTable {
  public static final Map<Integer, Integer> _DailyItem;
  
  private static final Log _log = LogFactory.getLog(ShopTable.class);
  
  private static final Map<Integer, L1Shop> _allShops = new HashMap<>();
  
  private static final Map<Integer, Integer> _allShopItem = new HashMap<>();
  
  private static final Map<Integer, Integer> _noBuyList = new HashMap<>();
  
  private static ShopTable _instance;
  
  static {
    _DailyItem = new HashMap<>();
  }
  
  public static ShopTable get() {
    if (_instance == null)
      _instance = new ShopTable(); 
    return _instance;
  }
  
  private static ArrayList<Integer> enumNpcIds() {
    ArrayList<Integer> ids = new ArrayList<>();
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("SELECT DISTINCT `npc_id` FROM `shop`");
      rs = pstm.executeQuery();
      while (rs.next())
        ids.add(Integer.valueOf(rs.getInt("npc_id"))); 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs, pstm, con);
    } 
    return ids;
  }
  
  private static L1Shop loadShop(int npcId, ResultSet rs) throws SQLException {
    List<L1ShopItem> sellingList = new ArrayList<>();
    List<L1ShopItem> purchasingList = new ArrayList<>();
    int currencyItemId = 40308;
    L1NpcTalkData action = NPCTalkDataTable.get().getTemplate(npcId);
    if (action != null && action.getCurrencyItemId() != 0)
      currencyItemId = action.getCurrencyItemId(); 
    while (rs.next()) {
      int itemId = rs.getInt("item_id");
      if (ItemTable.get().getTemplate(itemId) == null) {
        _log.error("商店贩卖资料错误: 没有这个编号的道具:" + itemId + " 对应NPC编号:" + npcId);
        delete(npcId, itemId);
        continue;
      } 
      int sellingPrice = rs.getInt("selling_price");
      int purchasingPrice = rs.getInt("purchasing_price");
      int packCount = rs.getInt("pack_count");
      String note = rs.getString("note");
      int enchantlevel = rs.getInt("enchant_level");
      int dailybuyingCount = rs.getInt("每日限购数量");
      if (dailybuyingCount > 0)
        _DailyItem.put(Integer.valueOf(itemId), Integer.valueOf(dailybuyingCount)); 
      Connection conI = null;
      PreparedStatement pstmI = null;
      ResultSet rsI = null;
      try {
        conI = DatabaseFactory.get().getConnection();
        pstmI = conI.prepareStatement("SELECT * FROM shop WHERE item_id='" + itemId + "'");
        rsI = pstmI.executeQuery();
        while (rsI.next()) {
          if (rsI.getInt("selling_price") >= 1 && purchasingPrice > rsI.getInt("selling_price")) {
            System.out.println(
                "侦测到买低卖高错误!!! NpcId=" + rsI.getInt("npc_id") + ", ItemID=" + itemId + ", 价格错误!!!");
            _log.error(
                "侦测到买低卖高错误!!! NpcId=" + rsI.getInt("npc_id") + ", ItemID=" + itemId + ", 价格错误!!!");
            purchasingPrice = sellingPrice >> 1;
          } 
        } 
        rsI.close();
      } catch (SQLException e) {
        _log.error(e.getLocalizedMessage(), e);
      } finally {
        SQLUtil.close(rsI, pstmI, conI);
      } 
      if (!note.contains("=>"))
        updata_name(npcId, itemId); 
      addSellList(itemId, sellingPrice, purchasingPrice, packCount);
      packCount = (packCount == 0) ? 1 : packCount;
      if (sellingPrice >= 0) {
        L1ShopItem l1ShopItem = new L1ShopItem(itemId, sellingPrice, packCount, enchantlevel, 
            dailybuyingCount);
        sellingList.add(l1ShopItem);
      } 
      if (purchasingPrice < 0)
        continue; 
      L1ShopItem item = new L1ShopItem(itemId, purchasingPrice, packCount, enchantlevel, 
          dailybuyingCount);
      purchasingList.add(item);
    } 
    return new L1Shop(npcId, currencyItemId, sellingList, purchasingList);
  }
  
  private static void updata_name(int npcId, int itemId) {
    Connection cn = null;
    PreparedStatement ps = null;
    String npcname = NpcTable.get().getNpcName(npcId);
    String itemname = ItemTable.get().getTemplate(itemId).getName();
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("UPDATE `shop` SET `note`=? WHERE `npc_id`=? AND `item_id`=?");
      int i = 0;
      ps.setString(++i, String.valueOf(String.valueOf(npcname)) + "=>" + itemname);
      ps.setInt(++i, npcId);
      ps.setInt(++i, itemId);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  private static void delete(int npc_id, int item_id) {
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("DELETE FROM `shop` WHERE `npc_id`=? AND `item_id`=?");
      ps.setInt(1, npc_id);
      ps.setInt(2, item_id);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  private static void addSellList(int itemId, int sellingPrice, int purchasingPrice, int packCount) {
    if (_noBuyList.get(Integer.valueOf(itemId)) != null)
      return; 
    Integer price = _allShopItem.get(new Integer(itemId));
    double value3 = 0.0D;
    if (purchasingPrice > 0) {
      if (packCount > 0) {
        value3 = (sellingPrice / packCount) / 2.0D;
      } else {
        value3 = purchasingPrice;
      } 
    } else if (sellingPrice > 0) {
      if (packCount > 0) {
        value3 = (sellingPrice / packCount) / 2.0D;
      } else {
        value3 = sellingPrice / 2.0D;
      } 
    } 
    if (value3 < 1.0D) {
      _noBuyList.put(new Integer(itemId), new Integer((int)value3));
      if (price != null)
        _allShopItem.remove(new Integer(itemId)); 
      return;
    } 
    if (price != null) {
      if (value3 < price.intValue())
        _allShopItem.put(new Integer(itemId), new Integer((int)value3)); 
    } else {
      _allShopItem.put(new Integer(itemId), new Integer((int)value3));
    } 
  }
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("SELECT * FROM shop WHERE npc_id=? ORDER BY order_id");
      Iterator<Integer> iterator = enumNpcIds().iterator();
      while (iterator.hasNext()) {
        int npcId = ((Integer)iterator.next()).intValue();
        ps.setInt(1, npcId);
        rs = ps.executeQuery();
        L1Shop shop = loadShop(npcId, rs);
        _allShops.put(Integer.valueOf(npcId), shop);
        rs.close();
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs, ps, cn);
    } 
    _log.info("载入商店贩卖资料数量: " + _allShops.size() + "(" + timer.get() + "ms)");
  }
  
  public int getPrice(int itemid) {
    int tgprice = 0;
    Integer price = _allShopItem.get(new Integer(itemid));
    if (price != null)
      tgprice = price.intValue(); 
    if (_noBuyList.get(Integer.valueOf(itemid)) != null)
      tgprice = 0; 
    return tgprice;
  }
  
  public L1Shop get(int npcId) {
    return _allShops.get(Integer.valueOf(npcId));
  }
}
